home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH20 / INT9.ASM < prev    next >
Encoding:
Assembly Source File  |  1994-07-23  |  18.6 KB  |  664 lines

  1. ; INT9.ASM
  2. ;
  3. ; A short TSR to provide a driver for the keyboard hardware interrupt.
  4. ;
  5. ; Note that this code does not patch into int 2Fh (multiplex interrupt)
  6. ; nor can you remove this code from memory except by rebooting.
  7. ; If you want to be able to do these two things (as well as check for
  8. ; a previous installation), see the chapter on resident programs.  Such
  9. ; code was omitted from this program because of length constraints.
  10. ;
  11. ;
  12. ; cseg and EndResident must occur before the standard library segments!
  13.  
  14. cseg        segment    para public 'code'
  15. OldInt9        dword    ?
  16. cseg        ends
  17.  
  18. ; Marker segment, to find the end of the resident section.
  19.  
  20. EndResident    segment    para public 'Resident'
  21. EndResident    ends
  22.  
  23.         .xlist
  24.         include     stdlib.a
  25.         includelib    stdlib.lib
  26.         .list
  27.  
  28.  
  29. NumLockScan    equ    45h
  30. ScrlLockScan    equ    46h
  31. CapsLockScan    equ    3ah
  32. CtrlScan    equ    1dh
  33. AltScan        equ    38h
  34. RShiftScan    equ    36h
  35. LShiftScan    equ    2ah
  36. InsScanCode    equ    52h
  37. DelScanCode    equ    53h
  38.  
  39. ; Bits for the various modifier keys
  40.  
  41. RShfBit        equ    1
  42. LShfBit        equ    2
  43. CtrlBit        equ    4
  44. AltBit        equ    8
  45. SLBit        equ    10h
  46. NLBit        equ    20h
  47. CLBit        equ    40h
  48. InsBit        equ    80h
  49.  
  50.  
  51. KbdFlags    equ    <byte ptr ds:[17h]>
  52. KbdFlags2    equ    <byte ptr ds:[18h]>
  53. KbdFlags3    equ    <byte ptr ds:[96h]>
  54. KbdFlags4    equ    <byte ptr ds:[97h]>
  55.  
  56. byp        equ    <byte ptr>
  57.  
  58.  
  59. cseg        segment    para public 'code'
  60.         assume    ds:nothing
  61.  
  62. ; Scan code translation table.
  63. ; The incoming scan code from the keyboard selects a row.
  64. ; The modifier status selects the column.
  65. ; The word at the intersection of the two is the scan/ASCII code to
  66. ; put into the PC's type ahead buffer.
  67. ; If the value fetched from the table is zero, then we do not put the
  68. ; character into the type ahead buffer.
  69. ;
  70. ;        norm   shft   ctrl   alt    num    caps   shcap  shnum
  71.  
  72. ScanXlat word    0000h, 0000h, 0000h, 0000h, 0000h, 0000h, 0000h, 0000h
  73.     word    011bh, 011bh, 011bh, 011bh, 011bh, 011bh, 011bh, 011bh    ;ESC
  74.     word    0231h, 0231h, 0000h, 7800h, 0231h, 0231h, 0231h, 0321h    ;1 !
  75.     word    0332h, 0340h, 0300h, 7900h, 0332h, 0332h, 0332h, 0332h    ;2 @
  76.     word    0433h, 0423h, 0000h, 7a00h, 0433h, 0433h, 0423h, 0423h    ;3 #
  77.     word    0534h, 0524h, 0000h, 7b00h, 0534h, 0534h, 0524h, 0524h    ;4 $
  78.     word    0635h, 0625h, 0000h, 7c00h, 0635h, 0635h, 0625h, 0625h    ;5 %
  79.     word    0736h, 075eh, 071eh, 7d00h, 0736h, 0736h, 075eh, 075eh    ;6 ^
  80.  
  81.     word    0837h, 0826h, 0000h, 7e00h, 0837h, 0837h, 0826h, 0826h    ;7 &
  82.     word    0938h, 092ah, 0000h, 7f00h, 0938h, 0938h, 092ah, 092ah    ;8 *
  83.     word    0a39h, 0a28h, 0000h, 8000h, 0a39h, 0a39h, 0a28h, 0a28h    ;9 (
  84.     word    0b30h, 0b29h, 0000h, 8100h, 0b30h, 0b30h, 0b29h, 0b29h    ;0 )
  85.     word    0c2dh, 0c5fh, 0000h, 8200h, 0c2dh, 0c2dh, 0c5fh, 0c5fh    ;- _
  86.     word    0d3dh, 0d2bh, 0000h, 8300h, 0d3dh, 0d3dh, 0d2bh, 0d2bh    ;= +
  87.     word    0e08h, 0e08h, 0e7fh, 0000h, 0e08h, 0e08h, 0e08h, 0e08h    ;bksp
  88.     word    0f09h, 0f00h, 0000h, 0000h, 0f09h, 0f09h, 0f00h, 0f00h    ;Tab
  89.  
  90. ;        norm   shft   ctrl   alt    num    caps   shcap  shnum
  91.     word    1071h, 1051h, 1011h, 1000h, 1071h, 1051h, 1051h, 1071h    ;Q
  92.     word    1177h, 1057h, 1017h, 1100h, 1077h, 1057h, 1057h, 1077h    ;W
  93.     word    1265h, 1245h, 1205h, 1200h, 1265h, 1245h, 1245h, 1265h    ;E
  94.     word    1372h, 1352h, 1312h, 1300h, 1272h, 1252h, 1252h, 1272h    ;R
  95.     word    1474h, 1454h, 1414h, 1400h, 1474h, 1454h, 1454h, 1474h    ;T
  96.     word    1579h, 1559h, 1519h, 1500h, 1579h, 1559h, 1579h, 1559h    ;Y
  97.     word    1675h, 1655h, 1615h, 1600h, 1675h, 1655h, 1675h, 1655h    ;U
  98.     word    1769h, 1749h, 1709h, 1700h, 1769h, 1749h, 1769h, 1749h    ;I
  99.  
  100.     word    186fh, 184fh, 180fh, 1800h, 186fh, 184fh, 186fh, 184fh    ;O
  101.     word    1970h, 1950h, 1910h, 1900h, 1970h, 1950h, 1970h, 1950h    ;P
  102.     word    1a5bh, 1a7bh, 1a1bh, 0000h, 1a5bh, 1a5bh, 1a7bh, 1a7bh    ;[ {
  103.     word    1b5dh, 1b7dh, 1b1dh, 0000h, 1b5dh, 1b5dh, 1b7dh, 1b7dh    ;] }
  104.     word    1c0dh, 1c0dh, 1c0ah, 0000h, 1c0dh, 1c0dh, 1c0ah, 1c0ah    ;enter
  105.     word    1d00h, 1d00h, 1d00h, 1d00h, 1d00h, 1d00h, 1d00h, 1d00h    ;ctrl
  106.     word    1e61h, 1e41h, 1e01h, 1e00h, 1e61h, 1e41h, 1e61h, 1e41h    ;A
  107.     word    1f73h, 1f5eh, 1f13h, 1f00h, 1f73h, 1f53h, 1f73h, 1f53h    ;S
  108.  
  109. ;        norm   shft   ctrl   alt    num    caps   shcap  shnum
  110.     word    2064h, 2044h, 2004h, 2000h, 2064h, 2044h, 2064h, 2044h    ;D
  111.     word    2166h, 2146h, 2106h, 2100h, 2166h, 2146h, 2166h, 2146h    ;F
  112.     word    2267h, 2247h, 2207h, 2200h, 2267h, 2247h, 2267h, 2247h    ;G
  113.     word    2368h, 2348h, 2308h, 2300h, 2368h, 2348h, 2368h, 2348h    ;H
  114.     word    246ah, 244ah, 240ah, 2400h, 246ah, 244ah, 246ah, 244ah    ;J
  115.     word    256bh, 254bh, 250bh, 2500h, 256bh, 254bh, 256bh, 254bh    ;K
  116.     word    266ch, 264ch, 260ch, 2600h, 266ch, 264ch, 266ch, 264ch    ;L
  117.     word    273bh, 273ah, 0000h, 0000h, 273bh, 273bh, 273ah, 273ah    ;; :
  118.  
  119.     word    2827h, 2822h, 0000h, 0000h, 2827h, 2827h, 2822h, 2822h    ;' "
  120.     word    2960h, 297eh, 0000h, 0000h, 2960h, 2960h, 297eh, 297eh    ;` ~
  121.     word    2a00h, 2a00h, 2a00h, 2a00h, 2a00h, 2a00h, 2a00h, 2a00h    ;LShf
  122.     word    2b5ch, 2b7ch, 2b1ch, 0000h, 2b5ch, 2b5ch, 2b7ch, 2b7ch    ;\ |
  123.     word    2c7ah, 2c5ah, 2c1ah, 2c00h, 2c7ah, 2c5ah, 2c7ah, 2c5ah    ;Z
  124.     word    2d78h, 2d58h, 2d18h, 2d00h, 2d78h, 2d58h, 2d78h, 2d58h    ;X
  125.     word    2e63h, 2e43h, 2e03h, 2e00h, 2e63h, 2e43h, 2e63h, 2e43h    ;C
  126.     word    2f76h, 2f56h, 2f16h, 2f00h, 2f76h, 2f56h, 2f76h, 2f56h    ;V
  127.  
  128. ;        norm   shft   ctrl   alt    num    caps   shcap  shnum
  129.     word    3062h, 3042h, 3002h, 3000h, 3062h, 3042h, 3062h, 3042h    ;B
  130.     word    316eh, 314eh, 310eh, 3100h, 316eh, 314eh, 316eh, 314eh    ;N
  131.     word    326dh, 324dh, 320dh, 3200h, 326dh, 324dh, 326dh, 324dh    ;M
  132.     word    332ch, 333ch, 0000h, 0000h, 332ch, 332ch, 333ch, 333ch    ;, <
  133.     word    342eh, 343eh, 0000h, 0000h, 342eh, 342eh, 343eh, 343eh    ;. >
  134.     word    352fh, 353fh, 0000h, 0000h, 352fh, 352fh, 353fh, 353fh    ;/ ?
  135.     word    3600h, 3600h, 3600h, 3600h, 3600h, 3600h, 3600h, 3600h    ;rshf
  136.     word    372ah, 0000h, 3710h, 0000h, 372ah, 372ah, 0000h, 0000h    ;* PS
  137.  
  138.     word    3800h, 3800h, 3800h, 3800h, 3800h, 3800h, 3800h, 3800h    ;alt
  139.     word    3920h, 3920h, 3920h, 0000h, 3920h, 3920h, 3920h, 3920h    ;spc
  140.     word    3a00h, 3a00h, 3a00h, 3a00h, 3a00h, 3a00h, 3a00h, 3a00h    ;caps
  141.     word    3b00h, 5400h, 5e00h, 6800h, 3b00h, 3b00h, 5400h, 5400h    ;F1
  142.     word    3c00h, 5500h, 5f00h, 6900h, 3c00h, 3c00h, 5500h, 5500h    ;F2
  143.     word    3d00h, 5600h, 6000h, 6a00h, 3d00h, 3d00h, 5600h, 5600h    ;F3
  144.     word    3e00h, 5700h, 6100h, 6b00h, 3e00h, 3e00h, 5700h, 5700h    ;F4
  145.     word    3f00h, 5800h, 6200h, 6c00h, 3f00h, 3f00h, 5800h, 5800h    ;F5
  146.  
  147. ;        norm   shft   ctrl   alt    num    caps   shcap  shnum
  148.     word    4000h, 5900h, 6300h, 6d00h, 4000h, 4000h, 5900h, 5900h    ;F6
  149.     word    4100h, 5a00h, 6400h, 6e00h, 4100h, 4100h, 5a00h, 5a00h    ;F7
  150.     word    4200h, 5b00h, 6500h, 6f00h, 4200h, 4200h, 5b00h, 5b00h    ;F8
  151.     word    4300h, 5c00h, 6600h, 7000h, 4300h, 4300h, 5c00h, 5c00h    ;F9
  152.     word    4400h, 5d00h, 6700h, 7100h, 4400h, 4400h, 5d00h, 5d00h    ;F10
  153.     word    4500h, 4500h, 4500h, 4500h, 4500h, 4500h, 4500h, 4500h    ;num
  154.     word    4600h, 4600h, 4600h, 4600h, 4600h, 4600h, 4600h, 4600h    ;scrl
  155.     word    4700h, 4737h, 7700h, 0000h, 4737h, 4700h, 4737h, 4700h    ;home
  156.  
  157.     word    4800h, 4838h, 0000h, 0000h, 4838h, 4800h, 4838h, 4800h    ;up
  158.     word    4900h, 4939h, 8400h, 0000h, 4939h, 4900h, 4939h, 4900h    ;pgup
  159.     word    4a2dh, 4a2dh, 0000h, 0000h, 4a2dh, 4a2dh, 4a2dh, 4a2dh    ;-
  160.     word    4b00h, 4b34h, 7300h, 0000h, 4b34h, 4b00h, 4b34h, 4b00h    ;left
  161.     word    4c00h, 4c35h, 0000h, 0000h, 4c35h, 4c00h, 4c35h, 4c00h    ;Cen
  162.     word    4d00h, 4d36h, 7400h, 0000h, 4d36h, 4d00h, 4d36h, 4d00h    ;right
  163.     word    4e2bh, 4e2bh, 0000h, 0000h, 4e2bh, 4e2bh, 4e2bh, 4e2bh    ;+
  164.     word    4f00h, 4f31h, 7500h, 0000h, 4f31h, 4f00h, 4f31h, 4f00h    ;end
  165.  
  166. ;        norm   shft   ctrl   alt    num    caps   shcap  shnum
  167.     word    5000h, 5032h, 0000h, 0000h, 5032h, 5000h, 5032h, 5000h    ;down
  168.     word    5100h, 5133h, 7600h, 0000h, 5133h, 5100h, 5133h, 5100h    ;pgdn
  169.     word    5200h, 5230h, 0000h, 0000h, 5230h, 5200h, 5230h, 5200h    ;ins
  170.     word    5300h, 532eh, 0000h, 0000h, 532eh, 5300h, 532eh, 5300h    ;del
  171.     word    0,0,0,0,0,0,0,0                        ; --
  172.     word    0,0,0,0,0,0,0,0                        ; --
  173.     word    0,0,0,0,0,0,0,0                        ; --
  174.     word    5700h, 0000h, 0000h, 0000h, 5700h, 5700h, 0000h, 0000h    ;F11
  175.  
  176.     word    5800h, 0000h, 0000h, 0000h, 5800h, 5800h, 0000h, 0000h    ;F12
  177.  
  178.  
  179.  
  180. ;****************************************************************************
  181. ;
  182. ; AL contains keyboard scan code.
  183.  
  184. PutInBuffer     proc    near
  185.         push    ds
  186.         push    bx
  187.  
  188.         mov     bx, 40h                 ;Point ES at the BIOS
  189.         mov     ds, bx                  ; variables.
  190.  
  191. ; If the current scan code is E0 or E1, we need to take note of this fact
  192. ; so that we can properly process cursor keys.
  193.  
  194.         cmp    al, 0e0h
  195.         jne    TryE1
  196.         or    KbdFlags3, 10b        ;Set E0 flag
  197.         and    KbdFlags3, 0FEh        ;Clear E1 flag
  198.         jmp    Done
  199.  
  200. TryE1:        cmp    al, 0e1h
  201.         jne    DoScan
  202.         or    KbdFlags3, 1        ;Set E1 flag
  203.         and    KbdFlags3, 0FDh        ;Clear E0 Flag
  204.         jmp    Done
  205.  
  206.  
  207. ; Before doing anything else, see if this is Ctrl-Alt-Del:
  208.  
  209. DoScan:        cmp    al, DelScanCode        ;5300h
  210.         jnz    TryIns
  211.         mov    bl, KbdFlags
  212.         and    bl, AltBit or CtrlBit    ;Alt = bit 3, ctrl = bit 2
  213.         cmp    bl, AltBit or CtrlBit
  214.         jne    DoPIB
  215.         mov    word ptr ds:[72h], 1234h    ;Warm boot flag.
  216.         jmp    dword ptr cs:RebootAdrs        ;REBOOT Computer
  217.  
  218. RebootAdrs    dd    0ffff0000h            ;Reset address.
  219.  
  220.  
  221. ; Check for the INS key here.  This one needs to toggle the ins bit
  222. ; in the keyboard flags variables.
  223.  
  224. TryIns:        cmp    al, InsScanCode
  225.         jne    TryInsUp
  226.         or    KbdFlags2, InsBit        ;Note INS is down.
  227.         jmp     doPIB                ;Pass on INS key.
  228.  
  229. TryInsUp:    cmp    al, InsScanCode+80h        ;INS up scan code.
  230.         jne    TryLShiftDn
  231.         and    KbdFlags2, not InsBit         ;Note INS is up.
  232.         xor    KbdFlags, InsBit        ;Toggle INS bit.
  233.         jmp    QuitPIB
  234.  
  235. ; Handle the left and right shift keys down here.
  236.  
  237. TryLShiftDn:    cmp    al, LShiftScan
  238.         jne    TryLShiftUp
  239.         or    KbdFlags, LShfBit        ;Note that the left
  240.         jmp    QuitPIB                ; shift key is down.
  241.  
  242. TryLShiftUp:    cmp    al, LShiftScan+80h
  243.         jne    TryRShiftDn
  244.         and    KbdFlags, not LShfBit        ;Note that the left
  245.         jmp    QuitPIB                ; shift key is up.
  246.  
  247.  
  248. TryRShiftDn:    cmp    al, RShiftScan
  249.         jne    TryRShiftUp
  250.         or    KbdFlags, RShfBit        ;Right shf is down.
  251.         jmp    QuitPIB
  252.  
  253. TryRShiftUp:    cmp    al, RShiftScan+80h
  254.         jne    TryAltDn
  255.         and    KbdFlags, not RShfBit          ;Right shf is up.
  256.         jmp    QuitPIB
  257.  
  258. ; Handle the ALT key down here.
  259.  
  260. TryAltDn:    cmp    al, AltScan
  261.         jne    TryAltUp
  262.         or    KbdFlags, AltBit            ;Alt key is down.
  263. GotoQPIB:    jmp    QuitPIB
  264.  
  265. TryAltUp:    cmp    al, AltScan+80h
  266.         jne    TryCtrlDn
  267.         and    KbdFlags, not AltBit        ;Alt key is up.
  268.         jmp    DoPIB
  269.  
  270.  
  271. ; Deal with the control key down here.
  272.  
  273. TryCtrlDn:    cmp    al, CtrlScan
  274.         jne    TryCtrlUp
  275.         or    KbdFlags, CtrlBit        ;Ctrl key is down.
  276.         jmp    QuitPIB
  277.  
  278. TryCtrlUp:    cmp    al, CtrlScan+80h
  279.         jne    TryCapsDn
  280.         and    KbdFlags, not CtrlBit        ;Ctrl key is up.
  281.         jmp    QuitPIB
  282.  
  283. ; Deal with the CapsLock key down here.
  284.  
  285. TryCapsDn:    cmp    al, CapsLockScan
  286.         jne    TryCapsUp
  287.         or    KbdFlags2, CLBit        ;Capslock is down.
  288.         xor    KbdFlags, CLBit            ;Toggle capslock mode.
  289.         jmp    QuitPIB
  290.  
  291. TryCapsUp:    cmp    al, CapsLockScan+80h
  292.         jne    TrySLDn
  293.         and    KbdFlags2, not CLBit        ;Capslock is up.
  294.         call    SetLEDs
  295.         jmp    QuitPIB
  296.  
  297. ; Deal with the Scroll Lock key down here.
  298.  
  299. TrySLDn:    cmp    al, ScrlLockScan
  300.         jne    TrySLUp
  301.         or    KbdFlags2, SLBit        ;Scrl lock is down.
  302.         xor    KbdFlags, SLBit            ;Toggle scrl lock.
  303.         jmp    QuitPIB
  304.  
  305. TrySLUp:    cmp    al, ScrlLockScan+80h
  306.         jne    TryNLDn
  307.         and    KbdFlags2, not SLBit        ;Scrl lock is up.
  308.         call    SetLEDs
  309.         jmp    QuitPIB
  310.  
  311. ; Handle the NumLock key down here.
  312.  
  313.  
  314. TryNLDn:           cmp    al, NumLockScan
  315.         jne    TryNLUp
  316.         or    KbdFlags2, NLBit        ;Numlock is down.
  317.         xor    KbdFlags, NLBit            ;Toggle numlock.
  318.         jmp    QuitPIB
  319.  
  320. TryNLUp:    cmp    al, NumLockScan+80h
  321.         jne     DoPIB
  322.         and    KbdFlags2, not NLBit        ;Numlock is up.
  323.         call    SetLEDs
  324.         jmp    QuitPIB
  325.  
  326.  
  327.  
  328. ; Handle all the other keys here:
  329.  
  330. DoPIB:        test    al, 80h            ;Ignore all other up keys.
  331.         jnz    QuitPIB
  332.  
  333. ; If the H.O. bit is set at this point, we'd best only have a zero in AL.
  334. ; Otherwise, this is an up code which we can safely ignore.
  335.  
  336.         call    Convert
  337.         test    ax, ax            ;Check for illegal code.
  338.         je    QuitPIB
  339.  
  340. PutCharInBuf:    push    cx
  341.         mov    cx, ax
  342.         mov    ah, 5            ;Store scan code into
  343.         int    16h            ; type ahead buffer.
  344.         pop    cx
  345.  
  346. QuitPIB:    and    KbdFlags3, 0FCh        ;E0, E1 not last code.
  347.  
  348. Done:        pop     bx
  349.         pop     ds
  350.         ret
  351. PutInBuffer     endp
  352.  
  353.  
  354.  
  355.  
  356. ;****************************************************************************
  357. ;
  358. ; Convert-    AL contains a PC Scan code.  Convert it to an ASCII char/Scan
  359. ;        code pair and return the result in AX.  This code assumes
  360. ;        that DS points at the BIOS variable space (40h).
  361.  
  362. Convert        proc    near
  363.         push    bx
  364.  
  365.         test    al, 80h            ;See if up code
  366.         jz    DownScanCode
  367.         mov    ah, al
  368.         mov    al, 0
  369.         jmp    CSDone
  370.  
  371. ; Okay, we've got a down key.  But before going on, let's see if we've
  372. ; got an ALT-Keypad sequence.
  373.  
  374. DownScanCode:    mov    bh, 0
  375.         mov    bl, al
  376.         shl    bx, 1            ;Multiply by eight to compute
  377.         shl    bx, 1            ; row index index the scan
  378.         shl    bx, 1            ; code xlat table
  379.  
  380. ; Compute modifier index as follows:
  381. ;
  382. ;    if alt then modifier = 3
  383.  
  384.         test    KbdFlags, AltBit
  385.         je    NotAlt
  386.         add    bl, 3
  387.         jmp    DoConvert
  388.  
  389. ;    if ctrl, then modifier = 2
  390.  
  391. NotAlt:        test    KbdFlags, CtrlBit
  392.         je    NotCtrl
  393.         add    bl, 2
  394.         jmp    DoConvert
  395.  
  396. ; Regardless of the shift setting, we've got to deal with numlock
  397. ; and capslock.  Numlock is only a concern if the scan code is greater
  398. ; than or equal to 47h.  Capslock is only a concern if the scan code
  399. ; is less than this.
  400.  
  401. NotCtrl:    cmp    al, 47h
  402.         jb    DoCapsLk
  403.         test    KbdFlags, NLBit            ;Test Numlock bit
  404.         je    NoNumLck
  405.         test    KbdFlags, LShfBit or RShfBit    ;Check l/r shift.
  406.         je    NumOnly
  407.         add    bl, 7                ;Numlock and shift.
  408.         jmp    DoConvert
  409.  
  410. NumOnly:    add    bl, 4                ;Numlock only.
  411.         jmp    DoConvert
  412.  
  413. ; If numlock is not active, see if a shift key is:
  414.  
  415. NoNumLck:    test    KbdFlags, LShfBit or RShfBit    ;Check l/r shift.
  416.         je    DoConvert            ;normal if no shift.
  417.         add    bl, 1
  418.         jmp    DoConvert
  419.  
  420. ; If the scan code's value is below 47h, we need to check for capslock.
  421.  
  422. DoCapsLk:       test    KbdFlags, CLBit            ;Chk capslock bit
  423.         je    DoShift
  424.         test    KbdFlags, LShfBit or RShfBit    ;Chk for l/r shift
  425.         je    CapsOnly
  426.         add    bl, 6                ;Shift and capslock.
  427.         jmp    DoConvert
  428.  
  429. CapsOnly:    add    bl, 5                ;Capslock
  430.         jmp    DoConvert
  431.  
  432. ; Well, nothing else is active, check for just a shift key.
  433.  
  434. DoShift:    test    KbdFlags, LShfBit or RShfBit    ;l/r shift.
  435.         je    DoConvert
  436.         add    bl, 1                ;Shift
  437.  
  438. DoConvert:    shl    bx, 1                ;Word array
  439.         mov    ax, ScanXlat[bx]
  440. CSDone:        pop    bx
  441.         ret
  442. Convert        endp
  443.  
  444.  
  445.  
  446.  
  447. ; SetCmd-    Sends the command byte in the AL register to the 8042
  448. ;        keyboard microcontroller chip (command register at
  449. ;        port 64h).
  450.  
  451. SetCmd        proc    near
  452.         push    cx
  453.         push    ax        ;Save command value.
  454.         cli            ;Critical region, no ints now.
  455.  
  456. ; Wait until the 8042 is done processing the current command.
  457.  
  458.         xor    cx, cx        ;Allow 65,536 times thru loop.
  459. Wait4Empty:    in    al, 64h        ;Read keyboard status register.
  460.         test    al, 10b        ;Input buffer full?
  461.         loopnz    Wait4Empty    ;If so, wait until empty.
  462.  
  463. ; Okay, send the command to the 8042:
  464.  
  465.         pop    ax        ;Retrieve command.
  466.         out    64h, al
  467.         sti            ;Okay, ints can happen again.
  468.         pop    cx
  469.         ret
  470. SetCmd        endp
  471.  
  472.  
  473.  
  474. ; SendCmd-    The following routine sends a command or data byte to the
  475. ;        keyboard data port (port 60h).
  476.  
  477. SendCmd        proc    near
  478.         push    ds
  479.         push    bx
  480.         push    cx
  481.         mov    cx, 40h
  482.         mov    ds, cx
  483.         mov    bx, ax        ;Save data byte
  484.  
  485.         mov    bh, 3        ;Retry cnt.
  486. RetryLp:    cli            ;Disable ints while accessing HW.
  487.  
  488. ; Clear the Error, Acknowledge received, and resend received flags
  489. ; in KbdFlags4
  490.  
  491.         and    byte ptr KbdFlags4, 4fh
  492.  
  493. ; Wait until the 8042 is done processing the current command.
  494.  
  495.         xor    cx, cx            ;Allow 65,536 times thru loop.
  496. Wait4Empty:    in    al, 64h            ;Read keyboard status register.
  497.         test    al, 10b            ;Input buffer full?
  498.         loopnz    Wait4Empty        ;If so, wait until empty.
  499.  
  500. ; Okay, send the data to port 60h
  501.  
  502.         mov    al, bl
  503.         out    60h, al
  504.         sti                ;Allow interrupts now.
  505.  
  506. ; Wait for the arrival of an acknowledgement from the keyboard ISR:
  507.  
  508.         xor    cx, cx            ;Wait a long time, if need be.
  509. Wait4Ack:    test    byp KbdFlags4, 10h    ;Acknowledge received bit.
  510.         jnz    GotAck
  511.         loop    Wait4Ack
  512.         dec    bh            ;Do a retry on this guy.
  513.         jne     RetryLp
  514.  
  515. ; If the operation failed after 3 retries, set the error bit and quit.
  516.  
  517.         or    byp KbdFlags4, 80h    ;Set error bit.
  518.  
  519. GotAck:        pop    cx
  520.         pop    bx
  521.         pop    ds
  522.         ret
  523. SendCmd        endp
  524.  
  525.  
  526.  
  527.  
  528. ; SetLEDs-    Updates the KbdFlags4 LED bits from the KbdFlags
  529. ;        variable and then transmits new flag settings to
  530. ;        the keyboard.
  531.  
  532. SetLEDs        proc    near
  533.         push    ax
  534.         push    cx
  535.         mov    al, KbdFlags
  536.         mov     cl, 4
  537.         shr    al, cl
  538.         and    al, 111b
  539.         and    KbdFlags4, 0F8h        ;Clear LED bits.
  540.         or    KbdFlags4, al        ;Mask in new bits.
  541.         mov    ah, al            ;Save LED bits.
  542.  
  543.         mov    al, 0ADh        ;Disable kbd for now.
  544.         call    SetCmd
  545.  
  546.         mov    al, 0EDh        ;8042 set LEDs cmd.
  547.         call    SendCmd            ;Send the command to 8042.
  548.         mov    al, ah            ;Get parameter byte
  549.         call    SendCmd            ;Send parameter to the 8042.
  550.  
  551.         mov    al, 0AEh        ;Reenable keyboard.
  552.         call    SetCmd
  553.         mov    al, 0F4h        ;Restart kbd scanning.
  554.         call    SendCmd
  555.         pop    cx
  556.         pop    ax
  557.         ret
  558. SetLEDs        endp
  559.  
  560.  
  561. ; MyInt9-    Interrupt service routine for the keyboard hardware
  562. ;        interrupt.
  563.  
  564. MyInt9        proc    far
  565.         push    ds
  566.         push    ax
  567.         push    cx
  568.  
  569.         mov    ax, 40h
  570.         mov    ds, ax
  571.  
  572.         mov    al, 0ADh        ;Disable keyboard
  573.         call    SetCmd
  574.         cli                ;Disable interrupts.
  575.         xor    cx, cx
  576. Wait4Data:    in    al, 64h            ;Read kbd status port.
  577.         test    al, 10b            ;Data in buffer?
  578.         loopz    Wait4Data        ;Wait until data available.
  579.         in    al, 60h            ;Get keyboard data.
  580.         cmp    al, 0EEh        ;Echo response?
  581.         je    QuitInt9
  582.         cmp    al, 0FAh        ;Acknowledge?
  583.         jne    NotAck
  584.         or    KbdFlags4, 10h        ;Set ack bit.
  585.         jmp    QuitInt9
  586.  
  587. NotAck:        cmp    al, 0FEh        ;Resend command?
  588.         jne    NotResend
  589.         or    KbdFlags4, 20h        ;Set resend bit.
  590.         jmp    QuitInt9
  591.  
  592. ; Note: other keyboard controller commands all have their H.O. bit set
  593. ; and the PutInBuffer routine will ignore them.
  594.  
  595. NotResend:    call    PutInBuffer        ;Put in type ahead buffer.
  596.  
  597. QuitInt9:    mov    al, 0AEh        ;Reenable the keyboard
  598.         call    SetCmd
  599.  
  600.         mov    al, 20h            ;Send EOI (end of interrupt)
  601.         out    20h, al            ; to the 8259A PIC.
  602.         pop    cx
  603.         pop    ax
  604.         pop    ds
  605.         iret
  606. MyInt9        endp
  607.  
  608.  
  609.  
  610. Main        proc
  611.         assume    ds:cseg
  612.  
  613.         mov    ax, cseg
  614.         mov    ds, ax
  615.  
  616.         print
  617.         byte    "INT 9 Replacement",cr,lf
  618.         byte    "Installing....",cr,lf,0
  619.  
  620. ; Patch into the INT 9 interrupt vector.  Note that the
  621. ; statements above have made cseg the current data segment,
  622. ; so we can store the old INT 9 value directly into
  623. ; the OldInt9 variable.
  624.  
  625.         cli                ;Turn off interrupts!
  626.         mov    ax, 0
  627.         mov    es, ax
  628.         mov    ax, es:[9*4]
  629.         mov    word ptr OldInt9, ax
  630.         mov     ax, es:[9*4 + 2]
  631.         mov    word ptr OldInt9+2, ax
  632.         mov    es:[9*4], offset MyInt9
  633.         mov    es:[9*4+2], cs
  634.         sti                ;Okay, ints back on.
  635.  
  636.  
  637. ; We're hooked up, the only thing that remains is to terminate and
  638. ; stay resident.
  639.  
  640.         print
  641.         byte    "Installed.",cr,lf,0
  642.  
  643.         mov    ah, 62h            ;Get this program's PSP
  644.         int    21h            ; value.
  645.  
  646.         mov    dx, EndResident        ;Compute size of program.
  647.         sub    dx, bx
  648.         mov    ax, 3100h        ;DOS TSR command.
  649.         int    21h
  650. Main        endp
  651. cseg        ends
  652.  
  653. sseg        segment    para stack 'stack'
  654. stk        db    1024 dup ("stack   ")
  655. sseg        ends
  656.  
  657. zzzzzzseg    segment    para public 'zzzzzz'
  658. LastBytes    db    16 dup (?)
  659. zzzzzzseg    ends
  660.         end    Main
  661.  
  662.  
  663.  
  664.